
public class HashTableTest {
	void assertIsEmpty(HashTable table) throws TestException {
		if (!table.isEmpty()) {
			throw new TestException("New instance must be empty");
		}
		if (table.size()!=0) {
			throw new TestException("Size of the new instance must be 0. Actual is:"+table.size());			
		}
		if (table.get("1")!=null) {
			throw new TestException("New instance must not have any values");						
		}
		if (table.remove("2")!=null) {
			throw new TestException("New instance must not have any values");
		}
		
	}
	void testNewInstanceIsEmpty() throws TestException {
		HashTable table = newHashTable();
		assertIsEmpty(table);
	}
	
	void testSimplePut() throws TestException {
		HashTable table = newHashTable();
		table.put("key1", "value1");
		table.put("key2", "value2");
		String value1 = table.get("key1");
		if (!"value1".equals(value1)) {
			throw new TestException("Expected: table[key1]=value1. Actual: table[key1]="+value1);
		}
		String value2 = table.get("key2");
		if (!"value2".equals(value2)) {
			throw new TestException("Expected: table[key2]=value2. Actual: table[key2]="+value2);
		}
		if (table.isEmpty()) {
			throw new TestException("Table is not expected to be empty");
		}
		if (table.size()!=2) {
			throw new TestException("Expected: table.size=2. Actual: table.size="+table.size());
		}
	}
	
	void testRewritingPut() throws TestException {
		HashTable table = newHashTable();
		table.put("key1", "value1");
		table.put("key1", "value2");
		String value1 = table.get("key1");
		if (!"value2".equals(value1)) {
			throw new TestException("Expected: table[key1]=value2. Actual: table[key1]="+value1);
		}
		if (table.isEmpty()) {
			throw new TestException("Table is not expected to be empty");
		}
		if (table.size()!=1) {
			throw new TestException("Expected: table.size=1. Actual: table.size="+table.size());
		}
	}
	
	void testPutAndRemove() throws TestException {
		HashTable table = newHashTable();
		table.put("key1", "value1");
		table.put("key2", "value2");
		String value1 = table.remove("key1");
		if (!"value1".equals(value1)) {
			throw new TestException("Expected: table.remove(key1)=value1. Actual:"+value1);
		}
		value1 = table.get("key1");
		if (null!=value1) {
			throw new TestException("It is expected that there is no value after removing a key. Actual:"+value1);
		}
		if (table.isEmpty()) {
			throw new TestException("Table is not expected to be empty");
		}
		if (table.size()!=1) {
			throw new TestException("Expected: table.size=1. Actual: table.size="+table.size());
		}
		table.remove("key2");
		assertIsEmpty(table);
	}
	
	void testClear() throws TestException {
		HashTable table = newHashTable();
		table.put("key1", "value1");
		table.put("key2", "value2");
		table.clear();
		assertIsEmpty(table);
	}
	
	void testKiller() throws TestException {
		HashTable table = newHashTable();
		table.put("key1", "key1");
		for (int i=0; i<30; i++) {
			table.put(String.valueOf(i), "key1");
		}
		if (table.size()!=31) {
			throw new TestException();
		}
		table.remove("key1");
		for (int i=0; i<30; i++) {
			String value = table.get(String.valueOf(i));
			if (!"key1".equals(value)) {
				throw new TestException("wrong value="+value+" for key="+i);
			}
		}		
	}
	
	void runTests() throws TestException {
		System.out.println("HashTable test started");
		testNewInstanceIsEmpty();
		testSimplePut();
		testRewritingPut();
		testPutAndRemove();
		testClear();
		testKiller();
		System.out.println("HashTable test PASSED");
	}
	
	HashTable newHashTable() {
		return new HashTableImpl();
	}
	
	public static void main(String[] args) throws TestException {
		HashTableTest testCase = new HashTableTest();
		testCase.runTests();
	}
}
